using System;
using System.Collections.Generic;

namespace Tools
{
    public class Signal<T1, T2>
    {
        private event Action<T1, T2> _onceListener;
        protected readonly HashSet<Action<T1, T2>> _cachedOnceListeners;

        protected event Action<T1, T2> _listener;
        protected readonly HashSet<Action<T1, T2>> _cachedListeners;

        public Signal(int capcity = 8)
        {
            if (capcity <= 0) capcity = 8;
            _cachedListeners = new HashSet<Action<T1, T2>>(capcity);
            _cachedOnceListeners = new HashSet<Action<T1, T2>>(capcity);
        }

        public void AddOnce(Action<T1, T2> callback)
        {
            if (_cachedOnceListeners.Add(callback))
            {
                _onceListener += callback;
            }
        }

        public void AddListener(Action<T1, T2> callback)
        {
            if (_cachedListeners.Add(callback))
            {
                _listener += callback;
            }
        }

        public void RemoveListener(Action<T1, T2> callback)
        {
            if (_cachedListeners.Remove(callback))
            {
                _listener -= callback;
            }
        }

        private void RemoveOncedListener()
        {
            _onceListener = null;
            _cachedOnceListeners.Clear();
        }

        private void RemoveListener()
        {
            _listener = null;
            _cachedListeners.Clear();
        }

        public void RemoveAllListeners()
        {
            RemoveOncedListener();
            RemoveListener();
        }

        public void Dispatch(T1 t1, T2 t2)
        {
            _onceListener?.Invoke(t1, t2);
            RemoveOncedListener();
            _listener?.Invoke(t1, t2);
        }
    }
}